use core::{cell::UnsafeCell, mem::MaybeUninit, ops::Deref};

unsafe impl <T: Send> Send for UnsafeMut<T> {}
unsafe impl <T: Sync> Sync for UnsafeMut<T> {}

pub struct UnsafeMut<T> {
    value: UnsafeCell<MaybeUninit<T>>,
}

impl<T> Deref for UnsafeMut<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        unsafe { (& *self.value.get()).assume_init_ref() }
    }
}

impl<T> UnsafeMut<T> {

    pub const fn const_new() -> Self {
        Self { value: UnsafeCell::new(MaybeUninit::uninit()) }
    }

    pub unsafe fn init(&self, value: T) {
        (&mut *self.value.get()).write(value);
    }
}

unsafe impl <T: Send> Send for UnsafeInitMut<T> {}
unsafe impl <T: Sync> Sync for UnsafeInitMut<T> {}

pub struct UnsafeInitMut<T> {
    value: UnsafeCell<T>,
}

impl <T> Deref for UnsafeInitMut<T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        unsafe { &*self.value.get() }
    }
}

impl <T> UnsafeInitMut<T> {

    pub const fn const_new(value: T) -> Self {
        Self { value: UnsafeCell::new(value) }
    }
    
    pub const unsafe fn as_mut(&self) -> &mut T {
        &mut *self.value.get()
    }
}

